﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// 软体
/// </summary>
public class SoftBody : MonoBehaviour
{
    //力的参数
    public float intensity = 1f;
    [Header("质量")]
    public float mass = 1f;
    [Header("僵硬")]
    public float stiffness = 1f;
    [Header("阻尼")]
    public float damping = 0.78f;
    
    
    private Mesh originalMesh;
    private Mesh meshClone;
    private MeshRenderer renderer;

    private JellyVertex[] jv;
    private Vector3[] vertexArray;
    
    
    void Start()
    {
        originalMesh = GetComponent<MeshFilter>().sharedMesh;
        meshClone = Instantiate(originalMesh);
        GetComponent<MeshFilter>().sharedMesh = meshClone;
        renderer = GetComponent<MeshRenderer>();
        
        //复制一份顶点预先存储到一个数组中
        jv = new JellyVertex[meshClone.vertices.Length];
        for (int i = 0; i < meshClone.vertices.Length; i++)
        {
            var worldPos = transform.TransformPoint(meshClone.vertices[i]);        //模型顶点转换为世界坐标轴
            jv[i] = new JellyVertex(i,worldPos);
        }

    }

    public void FixedUpdate()
    {
        vertexArray = originalMesh.vertices;
        for (int i = 0; i < jv.Length; i++)
        {
            var v = jv[i];
            var point = vertexArray[v.index];
            Vector3 worldPoint = transform.TransformPoint(point);

            var bounds = renderer.bounds;
            float intensityVal = (1 - (bounds.max.y - worldPoint.y) 
                / bounds.size.y) * this.intensity;                //离边框距离越大的点,花费更多的时间运动过去
            
            v.Shake(worldPoint, mass, stiffness, damping);
            var newPoint = transform.InverseTransformPoint(v.position);
            vertexArray[v.index] = Vector3.Lerp(point, newPoint, intensityVal);
        }

        meshClone.vertices = vertexArray;
    }

    public class JellyVertex
    {
        /// <summary>
        /// 顶点下标值
        /// </summary>
        public int index;
        public Vector3 position;
        public Vector3 velocity;
        public Vector3 force;
        
        public JellyVertex(int index,Vector3 position)
        {
            this.index = index;
            this.position = position;
        }

        public void Shake(Vector3 target, float mass, float stiffness, float damping)
        {
            force = (target - position) * stiffness;
            velocity = (velocity + force / mass) * damping;
            position += velocity;

            var result = velocity + force + force / mass;
            if (result.magnitude < 0.001f)
            {
                position = target;
            }
        }


    }

}
